package com.sjgtw.cloud.web.freeze.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.sjgtw.cloud.common.core.utils.StringUtils;
import com.sjgtw.cloud.common.core.utils.bean.BeanUtils;
import com.sjgtw.cloud.common.core.web.controller.BaseController;
import com.sjgtw.cloud.common.core.web.domain.AjaxResult;
import com.sjgtw.cloud.common.core.web.page.TableDataInfo;
import com.sjgtw.cloud.constant.SjgtwConstont;
import com.sjgtw.cloud.util.EasyExcelUtil;
import com.sjgtw.cloud.web.freeze.domain.FreezeFallback;
import com.sjgtw.cloud.web.freeze.domain.FreezeRecord;
import com.sjgtw.cloud.web.freeze.domain.FreezeRestore;
import com.sjgtw.cloud.web.freeze.service.IFreezeFallbackService;
import com.sjgtw.cloud.web.freeze.service.IFreezeRecordService;
import com.sjgtw.cloud.web.freeze.service.IFreezeRestoreService;
import com.sjgtw.cloud.web.freeze.vo.ExportFreezeExcel;
import com.sjgtw.cloud.web.freeze.vo.ExportFreezeVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 冻害记录Controller
 *
 * @author lvyoufang
 * @date 2024-03-17
 */
@RestController
@RequestMapping("/freeze")
@Api(tags = "4.7、冻害记录")
public class FreezeRecordController extends BaseController
{
    @Autowired
    private IFreezeRecordService freezeRecordService;

    @Autowired
    private IFreezeFallbackService freezeFallbackService;

    @Autowired
    private IFreezeRestoreService freezeRestoreService;

    /**
     * 查询冻害记录列表
     */
    @ApiOperation(value = "查询冻害记录列表")
    @GetMapping("/list")
    public TableDataInfo list(FreezeRecord freezeRecord)
    {
        startPage();
        List<FreezeRecord> list = freezeRecordService.selectFreezeRecordList(freezeRecord);
        return getDataTable(list);
    }

    /**
     * 查询冻害-回落情况列表
     */
    @ApiOperation(value = "查询冻害-回落情况列表")
    @GetMapping("/listFallback")
    public TableDataInfo listFallback(FreezeFallback freezeFallback)
    {
        startPage();
        List<FreezeFallback> list = freezeFallbackService.selectFreezeFallbackList(freezeFallback);
        return getDataTable(list);
    }

    /**
     * 查询冻害-恢复情况列表
     */
    @ApiOperation(value = "查询冻害-恢复情况列表")
    @GetMapping("/listRestore")
    public TableDataInfo listRestore(FreezeRestore freezeRestore)
    {
        startPage();
        List<FreezeRestore> list = freezeRestoreService.selectFreezeRestoreList(freezeRestore);
        return getDataTable(list);
    }


    /**
     * 导出冻害记录列表
     */
    @ApiOperation(value = "导出冻害记录列表")
    @PostMapping("/export")
    public void export(HttpServletResponse response, FreezeRecord freezeRecord)
    {
        List<FreezeRecord> list = freezeRecordService.selectFreezeRecordList(freezeRecord);
        List<Long> freezeIds = list.stream().map(FreezeRecord::getId).collect(Collectors.toList());

        List<FreezeRestore> restores = freezeRestoreService.selectByFreezeIds(freezeIds);
        List<FreezeFallback> fallbacks = freezeFallbackService.selectByFreezeIds(freezeIds);

        Map<Long, List<FreezeRestore>> restoreMap = restores.stream().collect(Collectors.groupingBy(FreezeRestore::getFreezeId));
        Map<Long, List<FreezeFallback>> fallbackMap = fallbacks.stream().collect(Collectors.groupingBy(FreezeFallback::getFreezeId));

        List<ExportFreezeVO> freezes = new ArrayList<>();
        for (FreezeRecord record : list) {
            ExportFreezeVO vo = new ExportFreezeVO();
            BeanUtils.copyProperties(record, vo);

            vo.setMileage1(dealMileage(vo));

            List<FreezeRestore> restoreList = restoreMap.get(record.getId());
            if (restoreList != null && restoreList.size() > 0) {
                FreezeRestore restore = restoreList.get(restoreList.size() - 1);
                vo.setRestoreTime(restore.getRestoreTime());
                vo.setMileage2(restore.getMileage());
                vo.setRestoreLength(restore.getLength());
            }
            List<FreezeFallback> fallbackList = fallbackMap.get(record.getId());
            if (fallbackList != null && fallbackList.size() > 0) {
                FreezeFallback fallback = fallbackList.get(fallbackList.size() - 1);
                BeanUtils.copyProperties(fallback, vo);
            }
            freezes.add(vo);
        }
        Map<String, List<ExportFreezeVO>> freezeMap =
                freezes.stream().filter(e -> StringUtils.isNotEmpty(e.getFreezeType())).collect(Collectors.groupingBy(ExportFreezeVO::getFreezeType));

        try {
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("冻害记录", "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

            final ClassPathResource classPathResource = new ClassPathResource("template/freeze.xlsx");
            InputStream inputStream = classPathResource.getInputStream();

            List<ExportFreezeVO> exportFreeze1 = freezeMap.get(SjgtwConstont.FREEZE_TYPE_UP);
            List<ExportFreezeVO> exportFreeze2 = freezeMap.get(SjgtwConstont.FREEZE_TYPE_DOWN);

            ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(inputStream).build();
            if (exportFreeze1 != null) {
                addNum(exportFreeze1);
            } else {
                exportFreeze1 = new ArrayList<>();
            }
            WriteSheet writeSheet1 = EasyExcel.writerSheet("10mm以上 ").build();
            excelWriter.fill(exportFreeze1, writeSheet1);

            if (exportFreeze2 != null) {
                addNum(exportFreeze2);
            } else {
                exportFreeze2 = new ArrayList<>();
            }
            WriteSheet writeSheet2 = EasyExcel.writerSheet("10mm以下 ").build();
            excelWriter.fill(exportFreeze2, writeSheet2);

            // 千万别忘记关闭流
            excelWriter.finish();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private String dealMileage(ExportFreezeVO vo) {
        String result = "";
        if (StringUtils.isNotEmpty(vo.getXingType())) {
            result += vo.getXingType();
        }
        if (StringUtils.isNotEmpty(vo.getKilometer())) {
            String[] split = vo.getKilometer().split(",");
            result += "K" + split[0] + "+" + split[1] + "-" + "K" + split[2] + "+" + split[3];
        }
        if (StringUtils.isNotEmpty(vo.getRemark())) {
            result += "（" + vo.getRemark() + "）";
        }
        return result;
    }

    private void addNum(List<ExportFreezeVO> exportFreezes) {
        for (int i=0; i<exportFreezes.size(); i++) {
            exportFreezes.get(i).setNum(i+1);
        }
    }

    @ApiOperation(value = "下载模版")
    @PostMapping("/downloadTemplate")
    public void export(HttpServletResponse response)
    {
        try {
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("冻害记录模版", "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

            final ClassPathResource classPathResource = new ClassPathResource("template/freeze.xlsx");
            InputStream inputStream = classPathResource.getInputStream();

            ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(inputStream).build();
            WriteSheet writeSheet1 = EasyExcel.writerSheet("10mm以上 ").build();
            excelWriter.fill(new ArrayList<>(), writeSheet1);

            WriteSheet writeSheet2 = EasyExcel.writerSheet("10mm以下 ").build();
            excelWriter.fill(new ArrayList<>(), writeSheet2);

            // 千万别忘记关闭流
            excelWriter.finish();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 导入
     */
    @ApiOperation(value = "导入")
    @PostMapping("/importData")
    public AjaxResult importData(MultipartFile file)
    {
        EasyExcelUtil<ExportFreezeExcel> util = new EasyExcelUtil<>(ExportFreezeExcel.class);
        List<ExportFreezeExcel> excel1 = util.readExcel(file, 0, 5);
        List<ExportFreezeExcel> excel2 = util.readExcel(file, 1, 5);

        List<ExportFreezeVO> vos = new ArrayList<>();

        for (ExportFreezeExcel excel : excel1) {
            ExportFreezeVO vo = new ExportFreezeVO();
            BeanUtils.copyProperties(excel, vo);
            vo.setFreezeType(SjgtwConstont.FREEZE_TYPE_UP);
            vos.add(vo);
        }
        for (ExportFreezeExcel excel : excel2) {
            ExportFreezeVO vo = new ExportFreezeVO();
            BeanUtils.copyProperties(excel, vo);
            vo.setFreezeType(SjgtwConstont.FREEZE_TYPE_DOWN);
            vos.add(vo);
        }

        if (vos.size() == 0) {
            return error("没有读取到数据");
        }
        List<String> errors = freezeRecordService.check(vos);
        if (errors.size() > 0) {
            return AjaxResult.error("", errors);
        }
        List<FreezeRestore> restores = new ArrayList<>();
        List<FreezeFallback> fallbacks = new ArrayList<>();

        for (ExportFreezeVO vo : vos) {
            FreezeRecord freeze = new FreezeRecord();
            BeanUtils.copyProperties(vo, freeze);
            dealMileage(vo, freeze);
            freezeRecordService.insertFreezeRecord(freeze);

            if (vo.getRestoreTime() != null) {
                FreezeRestore restore = new FreezeRestore();
                BeanUtils.copyProperties(vo, restore);
                restore.setMileage(vo.getMileage2());
                restore.setLength(vo.getRestoreLength());
                restore.setFreezeId(freeze.getId());
                restores.add(restore);
            }
            if (vo.getFallbackTime() != null) {
                FreezeFallback fallback = new FreezeFallback();
                BeanUtils.copyProperties(vo, fallback);
                fallback.setFreezeId(freeze.getId());
                fallbacks.add(fallback);
            }
        }
        if (restores.size() > 0) {
            freezeRestoreService.batchSave(restores);
        }
        if (fallbacks.size() > 0) {
            freezeFallbackService.batchSave(fallbacks);
        }
        return success();
    }


    /**
     * 删除冻害记录
     */
    @GetMapping("/delete/{id}")
    @ApiOperation("删除冻害记录")
    public AjaxResult remove(@PathVariable Long id)
    {
        return toAjax(freezeRecordService.deleteAllRecord(id));
    }

    private void dealMileage(ExportFreezeVO vo, FreezeRecord freeze) {
        if (StringUtils.isNotEmpty(vo.getMileage1())) {
            String[] strings = splitString(vo.getMileage1());
            freeze.setXingType(strings[0]);
            freeze.setKilometer(strings[1]);
            freeze.setRemark(strings[2]);
        }
    }

    public static String extractNumbers(String input) {
        // 正则匹配数字（包括 + 之后的部分）
        Pattern pattern = Pattern.compile("\\d+");
        Matcher matcher = pattern.matcher(input);

        StringBuilder numbers = new StringBuilder();

        // 依次提取匹配到的数字
        while (matcher.find()) {
            if (numbers.length() > 0) {
                numbers.append(",");
            }
            numbers.append(matcher.group());
        }

        return numbers.toString();
    }

    public static String[] splitString(String input) {
        // 去掉整体前后的空白
        input = input.trim();

        // 查找括号位置（支持中英文括号）
        int leftParenIndex = Math.max(input.indexOf('('), input.indexOf('（'));
        int rightParenIndex = Math.max(input.indexOf(')'), input.indexOf('）'));

        // 提取括号内的内容
        String part3 = extractBracketContent(input, leftParenIndex, rightParenIndex);

        // 转换为小写以便兼容大小写 K
        String lowerInput = input.toLowerCase();
        // 判断是否存在 "K"
        int firstKIndex = lowerInput.indexOf('k');

        if (firstKIndex == -1) {
            // 如果没有 "K"
            String part1 = leftParenIndex != -1 ? input.substring(0, leftParenIndex).trim() : input;
            return new String[]{part1, "", part3};
        }

        // 如果存在 "K"
        String part1 = input.substring(0, firstKIndex).trim();
        String part2 = leftParenIndex != -1 ? input.substring(firstKIndex, leftParenIndex).trim()
                : input.substring(firstKIndex).trim();
        part2 = extractNumbers(part2);
        return new String[]{part1, part2, part3};
    }

    private static String extractBracketContent(String input, int leftParenIndex, int rightParenIndex) {
        if (leftParenIndex != -1 && rightParenIndex != -1 && leftParenIndex < rightParenIndex) {
            return input.substring(leftParenIndex + 1, rightParenIndex).trim();
        }
        return ""; // 如果括号不存在或无效，则返回空字符串
    }

}
